//进程间通信： 信号灯-->跟多线程编程中的信号量有什么区别？这个信号量是一个，信号灯是多个
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>

union semun {
    int              val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO                              (Linux-specific) */
};

/*
struct sembuf {
    unsigned short sem_num;  // 信号量在集合中的索引
    short          sem_op;   // 要执行的操作
    short          sem_flg;  // 操作标志
};
*/

union semun g_mysem;
struct sembuf g_sembuf;

int main(int argc, char *argv[]){
    int ret = 0;
    key_t key = ftok("./semget.txt", 'a');
    if(key < 0){
        perror("ftok() error:");
        exit(-1);
    }  

	//1、创建一个信号灯集合，3个信号量，数组的方式从0~2
    int semid = semget(key, 3, IPC_CREAT|0777);
    if(semid < 0){
        perror("semget() error:");
        exit(-1);
    }
    system("ipcs -s");
    //信号量的值其中一个进程初始化即可，这个是在写进程中执行的初始化

    g_sembuf.sem_num = 0; // 信号量在信号量集中的索引（0表示第一个信号量）
    g_sembuf.sem_flg = 0; //默认是阻塞操作，如IPC_NOWAIT, SEM_UNDO
    g_sembuf.sem_op = -1;  //p--操作，减少信号量的值
    semop(semid, &g_sembuf, 1); //阻塞操作
    
    printf("semget_read--> start\n");
    int j;
	while(j <= 10){
		printf("j = [%d]\n", j);
		j++;
		sleep(1);
	}	
	printf("semget_read--> end\n");

    ret = semctl(semid, 0, IPC_RMID, NULL);
    if(ret < 0){
        perror("semctl() error:");
        exit(-1);
    }
    return 0;
}
